package com.sgai.zero_robot.core;

import static com.sgai.zero_robot.core.Config.TAG_END;
import static com.sgai.zero_robot.core.Config.TAG_START;
import static com.sgai.zero_robot.core.Config.DOU;
import static com.sgai.zero_robot.core.Config.MAOHAO;
import static com.sgai.zero_robot.core.Config.SETDATA;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.NonNull;
import com.sgai.zero_robot.core.callback.AlarmCallback;
import com.sgai.zero_robot.core.callback.BatteryCallback;
import com.sgai.zero_robot.core.callback.CameraCallback;
import com.sgai.zero_robot.core.callback.ConfigCallback;
import com.sgai.zero_robot.core.callback.LaserRangingCallback;
import com.sgai.zero_robot.core.callback.LogCallback;
import com.sgai.zero_robot.core.callback.MoveSpeedCallback;
import com.sgai.zero_robot.core.callback.ReceveCallback;
import com.sgai.zero_robot.core.callback.RobotCallback;
import com.sgai.zero_robot.core.callback.SparkForkCallback;
import com.sgai.zero_robot.core.callback.SpeedRatioCallback;
import com.sgai.zero_robot.core.callback.SwingAngleCallback;
import com.sgai.zero_robot.core.io.RobotSerialManager;
import com.sgai.zero_robot.pojo.AlarmInfo;
import com.sgai.zero_robot.utils.LogUtil;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class RobotManagerFactory {
    protected final String TAG = "RobotManager";
    protected RobotSerialManager robotSerialManager;

    private static class Holder {
        private static final RobotManager INSTANCE = new RobotManager();
    }

    public static RobotManager getInstance() {
        return RobotManagerFactory.Holder.INSTANCE;
    }


    protected AtomicBoolean isInit = new AtomicBoolean(false);

    protected ReceveCallback messageCallback = new ReceveCallback() {
        @Override
        public void onMessage(String data) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    try{
                        handleMessage(data);
                    }catch (Exception e){
                        LogUtil.e(e,Thread.currentThread());
                    }

                }
            });
        }
    };
    protected AtomicBoolean isConnect = new AtomicBoolean(false);
    protected Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == timeWhat) {
                isConnect.set(false);
                robotSerialManager.close();
                robotSerialManager = new RobotSerialManager();
                boolean open = robotSerialManager.open("/dev/ttyHS0", 115200, messageCallback);
                if (open) {
                    isInit.set(true);
                }
                if (handler != null) {
                    handler.sendEmptyMessageDelayed(timeWhat, timeDelay);
                }
            }
        }
    };
    public String leftSpeed;
    public String rightSpeed;
    public String frontLaserRanging;
    public String backLaserRanging;
    public String frontSwingMotor;
    public String backSwingMotor;
    public String frontSpark;
    public String backSpark;
    public String validTestValue;

    public String outIndex;
    public String inIndex;
    public AlarmInfo alarmInfo;
    public String swingInside;
    public String swingOutside;
    public String taskState;
    public String rateValue;
    public String ssw0Value;
    public String ssw1Value;
    public String ssw2Value;
    public String ssw3Value;
    public String boardTemperature;
    public String pitchValue;
    public String rollValue;
    public String yawValue;
    public String adjValue;
    public String infoValue;
    public String cameraOut;
    public String cameraMid;
    public String cameraIn;
    public int battery;
    public String batteryVolt;
    public String batteryCur;
    public String batterySoh;
    public String batteryCellTemp;
    public String batteryMOSTemp;
    public String batteryCount;
    public String batteryState1;
    public String batteryState2;
    public String batteryVol1;
    public String batteryVol2;
    public String batteryVol3;
    public String batteryVol4;
    protected long timeDelay = 10000;
    protected int timeWhat = 1;
    public Map<String, AlarmInfo> alarmInfoMap = new HashMap<>();
    protected List<MoveSpeedCallback> moveSpeedCallback = new ArrayList<>();
    protected List<LaserRangingCallback> laserRangingCallback = new ArrayList<>();
    protected List<SparkForkCallback> sparkForkCallback = new ArrayList<>();
    protected List<RobotCallback> robotCallback = new ArrayList<>();
    protected List<AlarmCallback> alarmCallback = new ArrayList<>();
    protected List<SwingAngleCallback> swingAngleCallback = new ArrayList<>();
    protected List<SpeedRatioCallback> speedRatioCallback = new ArrayList<>();
    protected List<ConfigCallback> configCallback = new ArrayList<>();
    protected List<CameraCallback> cameraCallback = new ArrayList<>();
    protected List<BatteryCallback> batteryCallbacks = new ArrayList<>();

    public abstract void handleMessage(String data);

    public abstract boolean init();

    public abstract boolean isConnect();

    public abstract void close();

    public abstract void setLogcallback(LogCallback logcallback);

    public abstract void removeLogCallback();

    public abstract void addMoveSpeedCallback(MoveSpeedCallback moveSpeedCallback);

    public abstract void removeMoveSpeedCallback(MoveSpeedCallback moveSpeedCallback);

    public abstract void addLaserRangingCallback(LaserRangingCallback laserRangingCallback);

    public abstract void removeLaserRangingCallback(LaserRangingCallback laserRangingCallback);

    public abstract void addSparkForkCallback(SparkForkCallback sparkForkCallback);

    public abstract void removeSparkForkCallback(SparkForkCallback sparkForkCallback);

    public abstract void addRobotCallback(RobotCallback robotCallback);

    public abstract void removeRobotCallback(RobotCallback robotCallback);

    public abstract void addAlarmCallback(AlarmCallback alarmCallback);

    public abstract void removeAlarmCallback(AlarmCallback alarmCallback);

    public abstract void addSwingAngleCallback(SwingAngleCallback swingAngleCallback);

    public abstract void removeSwingAngleCallback(SwingAngleCallback swingAngleCallback);

    public abstract void addSpeedRatioCallback(SpeedRatioCallback speedRatioCallback);

    public abstract void removeSpeedRatioCallback(SpeedRatioCallback speedRatioCallback);

    public abstract void addConfigCallback(ConfigCallback configCallback);

    public abstract void removeConfigCallback(ConfigCallback configCallback);

    public abstract void addCameraCallback(CameraCallback cameraCallback);

    public abstract void removeCamareCallback(CameraCallback cameraCallback);


    public abstract void addBatteryCallback(BatteryCallback batteryCallback);

    public abstract void removeBatteryCallback(BatteryCallback batteryCallback);

    protected void sendConfig(int type, String value) {
        if (!isConnect.get()) {
            return;
        }
        if (!isInit.get()) {
            return;
        }
        LogUtil.e(TAG, "sendConfig  type:" + type + "   value:" + value);
        robotSerialManager.send(new StringBuilder(TAG_START).append(SETDATA).append(MAOHAO).append(type).append(DOU).append(value).append(TAG_END).toString().getBytes(StandardCharsets.UTF_8));
    }
}
